/*************************************************************************
|                                                                        |
|   READER.C                                                    28.05.94 |
|   ADMAKE Utility:  read in the makefile                                |
|                                                                        |
*************************************************************************/

#ifdef VMS
#include STDIO
#include STRING
#include STDLIB
#include CTYPE
#include "h.h"
#else
#include <stdio.h>
#include <string.h>
#ifdef HEAP
#include <heap.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include "h.h"
#endif

int                     lineno;

#ifdef PKANJI
/*************************************************************************
|                                                                        |
|   >>>>  ktest                                                          |
|                                                                        |
|   Return 0, 1 or 2 depending on whether the passed position in the     |
|   passed string is: not part of a Japanese DBCS character, the left    |
|   half of a DBCS character, or the right half of a DBCS character.     |
|                                                                        |
*************************************************************************/

#ifdef PANEWFD
static int ktest(char * p, int n)
#else
static int ktest(p,n)
char * p;                       /* source string */
int n;                          /* position to test */
#endif

{        
    register int i = 0;
    int c;

    for (;;)
    {
        c = (int)(*(p + i)) & 0xff;
        if (c == 0) return 0;
        if ( ( (c >= 0x81) && (c <= 0x9f) ) || 
            ( (c >= 0xe0) && (c <= 0xfc) ) )
        {
            if (i == n) return 1;
            if ((i + 1) == n) return 2;
            i += 2;
            continue;
        }
        if (i >= n) return 0;
        i++;
    }
}
#endif

/*************************************************************************
|                                                                        |
|   >>>>  getline                                                        |
|                                                                        |
|   Read a line into the supplied string of length LZ.  Remove           |
|   comments, ignore blank lines. Deal with quoted (\) #, and            |
|   quoted newlines.  If EOF return TRUE.                                |
|                                                                        |
*************************************************************************/

#ifdef PANEWFD
bool getline(char * str)
#else
bool getline(str)
char * str;
#endif

{
    register char *         p;
    char *                  q;
    char *                  a;
    int                     pos = 0;
    FILE *                  fd;
    FILE *                  incf;
    int                     specialhash;

    if (nestlvl < 0) 
    {
        lineno = 0;
        return TRUE;           /* EOF */
    }

    for (;;)
    {
        fd = ifile[nestlvl];
        if (fgets(str+pos, LZ-pos, fd) == (char *)0)
        {
            fclose(fd);
            if (nestlvl == 0) 
            {
                nestlvl--;
                ifeof();
                return TRUE;
            }
            fln[nestlvl] = 0;
            nestlvl--;
            continue;
        }
        lineno = ++fln[nestlvl];

        if ((p = strchr(str+pos, '\n')) == (char *)0)
            error("Input line is too long");

        if (p[-1] == '\\')
        {
            p[-1] = '\n';
            pos = (int)(p - str);
#ifdef PKANJI
            if (ktest(str,pos - 1) != 2) 
#endif
            continue;
        }

        if (!strncmp(str,"#ife",4)) specialhash = H_IFE;
        else if (!strncmp(str,"#ifne",5)) specialhash = H_IFNE;
        else if (!strncmp(str,"#ifn",4)) specialhash = H_IFN;
        else if (!strncmp(str,"#if",3)) specialhash = H_IF;
        else if (!strncmp(str,"#else",5)) specialhash = H_ELSE;
        else if (!strncmp(str,"#endif",6)) specialhash = H_ENDIF;
        else if (!strncmp(str,"#include",8)) specialhash = H_INCLUDE;
        else if (!strncmp(str,"#abort",6)) specialhash = H_ABORTEXIT;
        else specialhash = 0;

        p = str + (specialhash != H_NONE);
        while (((q = strchr(p, '#')) != (char *)0) &&
            (p != q) && (q[-1] == '\\'))
        {
            a = q - 1;      /*  Del \ chr; move rest back  */
            p = q;
            while ((*a++ = *q++) != '\0')
                ;
        }

        if (q != (char *)0) 
        {
            while ( (q != str) && (pspace(q[-1])) ) q--;
            if ((q > (str - 1)) && (q[-1] == '\\') && (q[-2] == '\\'))
            {
                q[-2] = '\n';
                pos = (int)(q - 1 - str);
#ifdef PKANJI
                if (ktest(str,pos - 1) != 2) 
#endif
                continue;
            }
            q[0] = '\n';
            q[1] = '\0';
        }

        if (ifproc(str,specialhash)) 
        {
            pos = 0;
            continue;
        }

        if (specialhash == H_INCLUDE)
        {
            q = str + 8;
            while (pspace(q[0])) q++;
            if (nestlvl >= 3)
                fatal(MSG[40]);         /* Include files nested too deeply */
            a = q + strlen(q) - 1;
            if (*a == '\n') *a = '\0';
            expand(q);
            incf = fopen(dollar(q),"r");
            if (incf == (FILE *)0)
                fatal(MSG[41], dollar(q));  /* Unable to open incl. file %s */
            ifile[++nestlvl] = incf;
            strncpy(fname[nestlvl],q,80);
            continue;
        }
        else if (specialhash == H_ABORTEXIT)
        {
            fprintf(stderr,"admake: %s",str + 1);
            resetcd();
            exit(PXERROR);
        }

        p = str;
        while (pspace(*p))     /*  Checking for blank  */
            p++;

        if ((*p == '\\') && (*(p + 1) == ' ')) *p = ' ';
        if (*p != '\0') return FALSE;
        pos = 0;
    }
}

/*************************************************************************
|                                                                        |
|   >>>>  gettok                                                         |
|                                                                        |
|   Get a word from the current line, surounded by white space.          |
|   return a pointer to it. String returned has no white spaces          |
|   in it.                                                               |
|                                                                        |
*************************************************************************/

#ifdef PANEWFD
char * gettok(char * * ptr)
#else 
char * gettok(ptr)
char * * ptr;
#endif

{
    register char *         p;

    while (pspace(**ptr)) (*ptr)++;         /* skip spaces  */
    if (**ptr == '\0') return NULL;         /* nothing after spaces  */
    p = *ptr;                               /* word starts here  */
    while ((**ptr != '\0') && (!pspace(**ptr))) (*ptr)++;  /* find word end */
    *(*ptr)++ = '\0';                       /* terminate it  */
    return(p);
}

/*************************************************************************
|                                                                        |
|   >>>>  pspace                                                         |
|                                                                        |
|   Check that the character is whitespace.  Note that isspace gives an  |
|   undefined result if the character is not ASCII.                      |
|                                                                        |
*************************************************************************/

#ifdef PANEWFD
int pspace(int c)
#else
int pspace(c)
int c;
#endif

{
    return (isascii(c & 0xff) && isspace(c & 0xff));
}
